using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace ERPStudio
{
    //[assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode = true)]
    //[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")]
    public partial class FrmWindowsLogin : Form
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private /*unsafe*/ static extern int FormatMessage(int dwFlags, ref IntPtr lpSource,
            int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize, ref IntPtr Arguments);
        
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
            int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

        // GetErrorMessage formats and returns an error message
        // corresponding to the input errorCode.
        public /*unsafe*/ static string GetErrorMessage(int errorCode)
        {
            int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
            int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
            int FORMAT_MESSAGE_FROM_SYSTEM  = 0x00001000;

            //int errorCode = 0x5; //ERROR_ACCESS_DENIED
            //throw new System.ComponentModel.Win32Exception(errorCode);

            int messageSize = 255;
            String lpMsgBuf = "";
            int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;

            IntPtr ptrlpSource = IntPtr.Zero;
            IntPtr prtArguments = IntPtr.Zero;
            
            int retVal = FormatMessage(dwFlags, ref ptrlpSource, errorCode, 0, ref lpMsgBuf, messageSize, ref prtArguments);
            if (0 == retVal)
            {
                throw new Exception("Failed to format message for error code " + errorCode + ". ");
            }

            return lpMsgBuf;
        }

        public void MyTrace(String val)
        {
            Trace.WriteLine("[" + DateTime.Now.ToString() + "]" + val);
        }

        public FrmWindowsLogin()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr tokenHandle = new IntPtr(0);
            IntPtr dupeTokenHandle = new IntPtr(0);
            try
            {
                string userName, domainName;
                // Get the user token for the specified user, domain, and password using the 
                // unmanaged LogonUser method.  
                // The local machine name can be used for the domain name to impersonate a user on this machine.                
                domainName = textBoxDomeniu.Text;                
                userName = textBoxUtilizator.Text;
                
                const int LOGON32_PROVIDER_DEFAULT = 0;
                //This parameter causes LogonUser to create a primary token.
                const int LOGON32_LOGON_INTERACTIVE = 2;
                //const int SecurityImpersonation = 2;

                tokenHandle = IntPtr.Zero;
                dupeTokenHandle = IntPtr.Zero;

                // Call LogonUser to obtain a handle to an access token.
                bool returnValue = LogonUser(userName, domainName, Console.ReadLine(), 
                    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    ref tokenHandle);

                if (false == returnValue)
                {
                    int ret = Marshal.GetLastWin32Error();
                    MyTrace("LogonUser failed with error code : " +  ret.ToString());
                    MyTrace("\nError: [" +  ret.ToString()  + "], " +  GetErrorMessage(ret).ToString());
                    int errorCode = 0x5; //ERROR_ACCESS_DENIED
                    throw new System.ComponentModel.Win32Exception(errorCode);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("Exception occurred. " + ex.Message);
            }
        }
    }
}